package biback.domain.customer

import biback.domain._
import biback.domain.account._
import biback.domain.common.{CommonAlgebra, TrnContext}
import biback.domain.product.BaseProduct._
import biback.domain.product._
import biback.utils.RegistryAlgebra
import cats.Monad

class AccountOpenService[F[_] : Monad]
(
  algebra: RegistryAlgebra[F] with PersonalAlgebra[F] with ProductAlgebra[F] with CommonAlgebra[F]
) extends DomainService[F, OpenAccountRequest, Unit] {
  import algebra._
  def run(ctx: TrnContext, o: OpenAccountRequest): ErrOrNoneF = {
    for {
      b <- customer.foundCustomerBase(o.idType, o.idNo)
      _ <- o.sms.map(m => common.smsValidated(b.mobile, m)).getOrElse(resultF(()))
      s <- product.found(o.prdCode)
      a <- product.foundParam(s.base)
      _ <- orF(openPreCheck(ctx, o, s, a))
      p <- registry.refFor[PersonalEntity](b.cNo.value)
      i <- customer.createAcctId()
      n <- customer.createAcctNo()
      e <- p.ask(OpenAccount(ctx, i, n, s, a))
    } yield e
  }

  def openPreCheck(ctx: TrnContext, o: OpenAccountRequest, product: SaleableProduct, param: ProductParam): ErrOrNone = {
    import ProductParam._
    product.base match {
      case CurrentDeposit1st =>
        val inputs = new OpenChannelSetter with OpenCurrencySetter with OpenBranchSetter with CertSetter with IdValidatedSetter {
          val openChannel = ctx.channel
          val openCurrency = product.ccy
          val openBranch = ctx.quota.brcNo
          val cert = o.cert
          val idValidated: IdValidationType = IdValidationType.CounterValidated
        }
        CurrentDeposit1st.openPre(param, inputs)
      case CurrentDeposit2nd =>
        val inputs = new OpenChannelSetter with OpenCurrencySetter with OpenBranchSetter {
          val openChannel = ctx.channel
          val openCurrency = product.ccy
          val openBranch = ctx.quota.brcNo
        }
        CurrentDeposit2nd.openPre(param, inputs)
    }
  }
}

case class OpenAccountRequest
(
  idType: PersonalIdType,
  idNo: IdNo,
  prdCode: ProductCode,
  trnAmt: NnDec = NnDec0,
  sms: Option[SMSVCode] = None,
  cert: Option[OneCertificate] = None
)
